﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PDX.ContextManagement;

namespace PDX.Services
{
    public class RegistrationBuilder
    {
        protected IServiceProvider Provider { get; private set; }

        public RegistrationBuilder(IServiceProvider provider)
        {
            this.Provider = provider;
        }

        protected void Blacklist<TImplementation>()
        {
            blacklisted.Add(typeof(TImplementation));
        }

        HashSet<Type> blacklisted = new HashSet<Type>();


        protected void Register<TService, TImplementation>(Func<TImplementation> factory)
            where TService : class where TImplementation : TService
        {
            if (!blacklisted.Contains(typeof(TImplementation)))
            {
                Provider.Register<TService>(factory as Func<TService>);
            }
        }

        public virtual void RegisterAll()
        {
            RegisterSingletons();
            RegisterContextManagment();
            RegisterValidation();
            RegisterChangeTracking();
        }

        public virtual void RegisterSingletons()
        {
            // These can't be blacklisted easily... think about this.
            // Really, we probably won't have any singletons soon enough.
            // And any singletons are "must implement", so the preferred way would
            // be not to blacklist them but to set Singletons.Whatever = new MyImpl();
            Provider.Register<IPropertyModelFactory>(() => Singletons.PropertyModelFactory);
            Provider.Register<Notification.INotificationManagerFactory>(() => Singletons.NotificationManagerFactory);
            Provider.Register<IPropertyResolver>(() => Singletons.PropertyResolver);
        }

        public virtual void RegisterContextManagment()
        {
            Register<IAttacher<Context>, ContextAttacher>(() => new ContextAttacher());
        }

        public virtual void RegisterValidation()
        {
            Register<IAttacher<Context>, Validation.ValidationManagerAttacher>(
                () => new Validation.ValidationManagerAttacher());

            Register<Validation.IValidationAdapter, Validation.DataErrorInfoAdapter>(
                () => new Validation.DataErrorInfoAdapter());

            Register<Validation.IValidationAdapter, Validation.DataAnnotationsAdapter>(
                () => new Validation.DataAnnotationsAdapter());
        }

        public virtual void RegisterChangeTracking()
        {
            Register<IAttacher<Element>, ChangeTracking.ChangeTrackerAttacher>(
                () => new ChangeTracking.ChangeTrackerAttacher());
        }
    }
}
